package p.ithorns.framework.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 身份证验证规则：
 * 第十八位数字（校验码）的计算方法为：
 * 1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为：7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
 * 2.将这17位数字和系数相乘的结果相加与11进行相除。
 * 3.余数0 1 2 3 4 5 6 7 8 9 10这11个数字，其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
 * 4.例如 余数为 0 , 则身份证最后一位就是1
 * 余数为 2 , 则身份证最后一位就是罗马数字X
 * 余数为 10 , 则身份证最后一位就是2
 *
 * @author ithorns
 */
public class IdCardUtil {

    private static final Logger log = LoggerFactory.getLogger(IdCardUtil.class);

    // 身份证系数
    private final static int[] COEFFICIENT_ARR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    // 余数数组
    private final static int[] REMAINDER_ARR = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // 身份证号码第18位数组
    private final static int[] LAST_ARR = {1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2};

    /**
     * 校验是否为身份证号码
     *
     * @param idCard -身份证号
     * @return boolean
     */
    public static boolean isIdCardNo(String idCard) {
        try {
            if (!StringUtil.isEmpty(idCard) && idCard.length() == 18) {
                // 1.将身份证号码前面的17位数分别乘以不同的系数。
                int sum = 0;
                for (int i = 0; i < COEFFICIENT_ARR.length; i++) {
                    // Character.digit 在指定的基数返回字符ch的数值。如果基数是不在范围内MIN_RADIX≤基数≤MAX_RADIX或如果该值的通道是不是一个有效的数字在指定的基数-1，则返回。
                    // ch - the character to be converted(要转换的字符)
                    // ch - int类型，是字符的ASCII码，数字的ASCII码是48-57
                    // radix - the radix(基数) ----也就是进制数
                    sum += Character.digit(idCard.charAt(i), 10) * COEFFICIENT_ARR[i];
                }

                String matchDigit = "";
                for (int i = 0; i < REMAINDER_ARR.length; i++) {
                    int j = REMAINDER_ARR[i];
                    if (j == sum % 11) {
                        matchDigit = String.valueOf(LAST_ARR[i]);
                        if (LAST_ARR[i] > 57) {
                            matchDigit = String.valueOf((char) LAST_ARR[i]);
                        }
                    }
                }

                if (matchDigit.equals(idCard.substring(idCard.length() - 1))) {
                    return true;
                }
            }

        } catch (Exception e) {
            log.error(String.format("校验身份证出现异常%s", e));
        }

        return false;
    }

    /**
     * 身份证号码脱敏 只脱敏月日四位
     */
    public static String getNewIdCardNo(String idCard) {
        String tempIdCard = idCard;
        if (isIdCardNo(idCard)) {
            StringBuilder sb = new StringBuilder(idCard);
            sb.replace(10, 14, "****");
            tempIdCard = sb.toString();
        }

        return tempIdCard;
    }


}